package edu.scut.data;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.apache.commons.math.complex.Complex;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

import com.interpss.common.datatype.UnitType;
import com.interpss.core.aclf.AclfBranchCode;
import com.interpss.core.aclf.AclfGenCode;
import com.interpss.core.aclf.AclfLoadCode;
import com.interpss.core.aclf.AclfNetwork;
import com.interpss.pssl.simu.IpssAclf;
import com.interpss.pssl.simu.IpssAclf.AclfBusDSL;

// TODO：对于联络开关支路也存在末端负荷的问题
// 从Excel文件中读入配网数据
public class DistributionNetworkImporter {

	private String networkName;	// Excel数据文件名称
	private AclfNetwork network;	// InterPSS配网对象	
	private Collection<String> colInterconnectionID = new ArrayList<String>();	// 联络开关ID集合

	// 数据文件名的读操作
	public String getNetworkName() {
		return networkName;
	}

	// InterPSS配网对象的读操作
	public AclfNetwork getNetwork() {
		return network;
	}

	// 联络开关ID的读操作
	public Collection<String> getColInterconnectionID() {
		return colInterconnectionID;
	}

	// 构造函数，建立InterPSS配网对象
	public DistributionNetworkImporter(String networkName) {
		// 1. 初始化配网对象
		this.networkName = networkName;
		this.network = IpssAclf.createAclfNetwork("IEEE70").setBaseKva(100000.0).getAclfNet();
		Collection<Integer> colNormalStartNodes = new ArrayList<Integer>();
		Collection<Integer> colNormalEndNodes = new ArrayList<Integer>();
		Collection<Float> colNormalR = new ArrayList<Float>();
		Collection<Float> colNormalX = new ArrayList<Float>();
		Collection<Float> colNormalP = new ArrayList<Float>();
		Collection<Float> colNormalQ = new ArrayList<Float>();
		Collection<Integer> colInterconnectionStartNodes = new ArrayList<Integer>();
		Collection<Integer> colInterconnectionEndNodes = new ArrayList<Integer>();
		Collection<Float> colInterconnectionR = new ArrayList<Float>();
		Collection<Float> colInterconnectionX = new ArrayList<Float>();
		// 2. 读入Excel文件中的信息
		int rootNode = 0;
		float rootVoltage = 0;
		try {
			// 2.1. 打开Excel文件
			Workbook workbook = Workbook.getWorkbook(new File(networkName));
			// 2.2. 读入常规支路信息
			Sheet sheetNormal = workbook.getSheet("normal_branch");
			// 2.2.1. 读入Excel中的所有数据行
			for (int i = 0; i < sheetNormal.getRows(); i++) {
				int startNode = Integer.parseInt(sheetNormal.getCell(0, i).getContents());
				colNormalStartNodes.add(startNode);
				int endNode = Integer.parseInt(sheetNormal.getCell(1, i).getContents());
				colNormalEndNodes.add(endNode);
				float r = Float.parseFloat(sheetNormal.getCell(2, i).getContents());
				colNormalR.add(r);
				float x = Float.parseFloat(sheetNormal.getCell(3, i).getContents());
				colNormalX.add(x);
				float p = Float.parseFloat(sheetNormal.getCell(4, i).getContents());
				colNormalP.add(p);
				float q = Float.parseFloat(sheetNormal.getCell(5, i).getContents());
				colNormalQ.add(q);
			}
			// 2.3. 读入联络开关信息
			Sheet sheetInterconnection = workbook.getSheet("interconnection_switch");
			// 2.3.1. 读入Excel中的所有数据行
			for (int i = 0; i < sheetInterconnection.getRows(); i++) {
				int startNode = Integer.parseInt(sheetInterconnection.getCell(0, i).getContents());
				colInterconnectionStartNodes.add(startNode);
				int endNode = Integer.parseInt(sheetInterconnection.getCell(1, i).getContents());
				colInterconnectionEndNodes.add(endNode);
				float r = Float.parseFloat(sheetInterconnection.getCell(2, i).getContents());
				colInterconnectionR.add(r);
				float x = Float.parseFloat(sheetInterconnection.getCell(3, i).getContents());
				colInterconnectionX.add(x);
				float p = Float.parseFloat(sheetNormal.getCell(4, i).getContents());
				colNormalP.add(p);
				float q = Float.parseFloat(sheetNormal.getCell(5, i).getContents());
				colNormalQ.add(q);
			}
			// 2.4. 读入通用信息
			Sheet sheetGeneral = workbook.getSheet("general");
			rootNode = Integer.parseInt(sheetGeneral.getCell(1, 0).getContents());
			rootVoltage = Float.parseFloat(sheetGeneral.getCell(1, 1).getContents());
			// 2.5. 关闭Excel文件
			workbook.close();
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (BiffException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 3. 添加节点
		// 3.1. 获得最大节点编号
		int normalMaxStartNode = Collections.max(colNormalStartNodes);
		int normalMaxEndNode = Collections.max(colNormalEndNodes);
		int interconnectionMaxStartNode = Collections.max(colInterconnectionStartNodes);
		int interconnectionMaxEndNode = Collections.max(colInterconnectionEndNodes);
		int maxNode = Math.max(Math.max(normalMaxStartNode, normalMaxEndNode), Math.max(interconnectionMaxStartNode, interconnectionMaxEndNode));
		// 3.2. 添加各个节点
		for (int i = 1; i <= maxNode; i++) {
			// 3.2.1. 新建节点
			AclfBusDSL newBus = IpssAclf.addAclfBus("Bus" + i, "Bus " + i, this.network);
			// 3.2.2. 设定额定电压
			newBus.setBaseVoltage(rootVoltage, UnitType.kV);
			// 3.2.3. 设定节点发电机类型
			if (i == rootNode)	// 平衡节点
				newBus.setGenCode(AclfGenCode.SWING);
			else	// 非发电机节点
				newBus.setGenCode(AclfGenCode.NON_GEN);
			// 3.2.4. 设定节点电压初始值
			newBus.setVoltageSpec(1.0, UnitType.PU, 0.0, UnitType.Deg);
			// 3.2.5. 设定节点负荷信息
			float newP = 0, newQ = 0;
			int j = 0;
			for (int thisEndNode : colNormalEndNodes) {
				if (thisEndNode == i) {
					newP = (Float) colNormalP.toArray()[j];
					newQ = (Float) colNormalQ.toArray()[j];
					break;
				}
				j++;
			}
			if (newP == 0 && newQ == 0)
				newBus.setLoadCode(AclfLoadCode.NON_LOAD);
			else {
				newBus.setLoadCode(AclfLoadCode.CONST_P);
				newBus.setLoad(new Complex(newP, newQ), UnitType.kVA);
			}
		}			
		// 4. 添加支路
		// 4.1. 添加常规支路
		for (int j = 0; j < colNormalStartNodes.size(); j++) {
			int newStartNode = (Integer) colNormalStartNodes.toArray()[j];
			int newEndNode = (Integer) colNormalEndNodes.toArray()[j];
			IpssAclf.addAclfBranch("Bus" + newStartNode, "Bus" + newEndNode, "Branch" + (j + 1), this.network)
			.setBranchCode(AclfBranchCode.LINE)
			.setZ(new Complex((Float) colNormalR.toArray()[j], (Float) colNormalX.toArray()[j]), UnitType.Ohm);
		}
		// 4.2. 添加联络开关支路
		for (int j = 0; j < colInterconnectionStartNodes.size(); j++) {
			int newStartNode = (Integer) colInterconnectionStartNodes.toArray()[j];
			int newEndNode = (Integer) colInterconnectionEndNodes.toArray()[j];
			IpssAclf.addAclfBranch("Bus" + newStartNode, "Bus" + newEndNode, "Branch" + (j + 1 + colNormalStartNodes.size()), this.network)
			.setBranchCode(AclfBranchCode.LINE)
			.setZ(new Complex((Float) colInterconnectionR.toArray()[j], (Float) colInterconnectionX.toArray()[j]), UnitType.Ohm);
			// 加入联络开关ID集合
			this.colInterconnectionID.add("Bus" + newStartNode + "->Bus" + newEndNode + "(Branch" + (j + 1 + colNormalStartNodes.size()) + ")");
		}
	}
}